package cn.aicnn.chatssespringboot.service.Impl;

import cn.aicnn.chatssespringboot.dto.OOMAnalysisResponseDTO;
import cn.aicnn.chatssespringboot.exception.OOMAnalysisException;
import cn.aicnn.chatssespringboot.service.OOMAnalysisService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

@Service
public class OOMAnalysisServiceImpl implements OOMAnalysisService {


    @Override
    public OOMAnalysisResponseDTO analyzeOOMFile(MultipartFile file) {
        try (InputStream inputStream = file.getInputStream()) { // 直接使用文件流
            // 替换原来的FileInputStream逻辑
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(inputStream); // 直接从流解析
            doc.getDocumentElement().normalize();

            OOMAnalysisResponseDTO response = new OOMAnalysisResponseDTO();
            analyzeUseCaseDiagram(doc, response);
            analyzeClassDiagram(doc, response);
            // ...其他分析逻辑
            return response;
        } catch (Exception e) {
            throw new OOMAnalysisException("文件解析失败: " + e.getMessage(), e);
        }
    }

    private void analyzeUseCaseDiagram(Document doc, OOMAnalysisResponseDTO response) {
        // 用于格式化数字显示
        DecimalFormat df = new DecimalFormat("#0.00");

        double uaw = 0;
        double uucw = 0;
        double tcf = 0;
        double ef = 0;

        // 技术复杂度因子权重
        double[] tcfWeights = {2, 1, 1, 1, 1, 0.5, 0.5, 2, 1, 1, 1, 1, 1};
        // 环境因子权重
        double[] efWeights = {1.5, 0.5, 1, 0.5, 1, 2, -1, -1};

        // 计算参与者数量
        NodeList actorNodes = doc.getElementsByTagName("c:Actors");
        if (actorNodes.getLength() > 0) {
            Element actorsElement = (Element) actorNodes.item(0);
            NodeList actorList = actorsElement.getElementsByTagName("o:Actor");
            int actors = actorList.getLength();
            response.setActors(actors);



            // 计算未调整参与者权重(UAW)
            for (int i = 0; i < actorList.getLength(); i++) {
                Element actor = (Element) actorList.item(i);
                String actorType = actor.getElementsByTagName("a:Name").item(0).getTextContent();

                // 简单分类: 系统参与者权重1，人类参与者权重2
                if (actorType.contains("系统") || actorType.contains("System")) {
                    uaw += 1;
                } else {
                    uaw += 2;
                }
            }
            response.setUAW(uaw);
        }

        // 计算用例数量
        NodeList useCaseNodes = doc.getElementsByTagName("c:UseCases");
        if (useCaseNodes.getLength() > 0) {
            Element useCasesElement = (Element) useCaseNodes.item(0);
            NodeList useCaseList = useCasesElement.getElementsByTagName("o:UseCase");
            int useCases = useCaseList.getLength();
            response.setUseCases(useCases);


            // 计算未调整用例权重(UUCW)
            for (int i = 0; i < useCaseList.getLength(); i++) {
                Element useCase = (Element) useCaseList.item(i);
                String useCaseName = useCase.getElementsByTagName("a:Name").item(0).getTextContent();

                // 简单估算用例复杂度
                // 根据用例名称中的关键词判断复杂度
                if (useCaseName.contains("管理") || useCaseName.contains("维护") ||
                        useCaseName.contains("处理") || useCaseName.contains("复杂")) {
                    uucw += 15; // 复杂用例
                } else if (useCaseName.contains("查看") || useCaseName.contains("查询") ||
                        useCaseName.contains("显示") || useCaseName.contains("简单")) {
                    uucw += 5;  // 简单用例
                } else {
                    uucw += 10; // 中等复杂度用例
                }
            }
            response.setUUC(uucw);
        }

        // 这里简化处理，使用预设值(实际应根据项目情况评估)
        double[] tcfFactors = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; // 0-5的评分

        double sum = 0;
        for (int i = 0; i < tcfWeights.length; i++) {
            sum += tcfWeights[i] * tcfFactors[i];
        }

        tcf = 0.6 + (sum / 100);
        response.setTCF(tcf);

        // 环境因子(EF)计算
        // 这里简化处理，使用预设值(实际应根据项目团队情况评估)
        double[] efFactors = {3, 3, 3, 3, 3, 3, 3, 3}; // 0-5的评分

        double sum1 = 0;
        for (int i = 0; i < efWeights.length; i++) {
            sum1 += efWeights[i] * efFactors[i];
        }

        ef = Double.parseDouble(df.format(1.4 + (-0.03 * sum1)));
        response.setEF(ef);

        // 计算未调整用例点(UUCP)
        double uucp = uaw + uucw;

        // 计算调整后用例点(UCP)
        int useCasePoints = (int) Math.round(uucp * tcf * ef);
        response.setUseCasePoints(useCasePoints);
    }


    private void analyzeClassDiagram(Document doc, OOMAnalysisResponseDTO response) {
        NodeList classList = doc.getElementsByTagName("Class");
        NodeList interfaceList = doc.getElementsByTagName("Interface");

        int totalClasses = classList.getLength() + interfaceList.getLength();

        response.setWmc(countMethods(doc));
        response.setDit(calculateMaxDepth(doc));
        response.setNoc(countSubclasses(doc));
        response.setCbo(calculateCoupling(doc));
        response.setRfc(response.getWmc() + response.getCbo());
        response.setLcom(calculateLackOfCohesion(doc));

    }

    // 辅助方法实现...
    private int countMethods(Document doc) {
        NodeList methods = doc.getElementsByTagName("o:Operation");
        System.out.println("methods="+methods);
        return methods.getLength();
    }

    private int calculateMaxDepth(Document doc) {
        // 继承树深度(DIT) - 从类到根的最大长度
        // 需要分析继承关系
        Map<String, Integer> ditMap = new HashMap<>();
        NodeList classNodes = doc.getElementsByTagName("o:Class");

        // 初始化DIT为1
        for (int i = 0; i < classNodes.getLength(); i++) {
            Element classElement = (Element) classNodes.item(i);
            String classId = classElement.getAttribute("Id");
            ditMap.put(classId, 1);
        }

        // 计算继承深度
        for (int i = 0; i < classNodes.getLength(); i++) {
            Element classElement = (Element) classNodes.item(i);
            String classId = classElement.getAttribute("Id");

            NodeList generalizations = classElement.getElementsByTagName("o:Generalization");
            for (int j = 0; j < generalizations.getLength(); j++) {
                Element generalization = (Element) generalizations.item(j);
                String parentId = generalization.getAttribute("Target");

                if (ditMap.containsKey(parentId)) {
                    ditMap.put(classId, ditMap.get(parentId) + 1);
                }
            }
        }

        // 找出最大DIT
        return ditMap.values().stream().max(Integer::compare).orElse(0);
    }

    private int countSubclasses(Document doc) {
        NodeList classNodes = doc.getElementsByTagName("o:Class");
        // 子类数(NOC) - 直接子类数量
        Map<String, Integer> nocMap = new HashMap<>();
        for (int i = 0; i < classNodes.getLength(); i++) {
            Element classElement = (Element) classNodes.item(i);
            String classId = classElement.getAttribute("Id");
            nocMap.put(classId, 0);
        }

        for (int i = 0; i < classNodes.getLength(); i++) {
            Element classElement = (Element) classNodes.item(i);
            NodeList generalizations = classElement.getElementsByTagName("o:Generalization");

            for (int j = 0; j < generalizations.getLength(); j++) {
                Element generalization = (Element) generalizations.item(j);
                String parentId = generalization.getAttribute("Target");

                if (nocMap.containsKey(parentId)) {
                    nocMap.put(parentId, nocMap.get(parentId) + 1);
                }
            }
        }
        return nocMap.values().stream().max(Integer::compare).orElse(0);
    }

    private int calculateCoupling(Document doc) {
        // 类间耦合度(CBO) - 与其他类的耦合数量
        // 这里简化处理，计算关联关系数量
        NodeList associations = doc.getElementsByTagName("o:Association");
        return associations.getLength();
    }

    private int calculateLackOfCohesion(Document doc) {
        return 0;
    }
}